package cc.rengu.igas.cops.core.service.trans.merchant;

import cc.rengu.igas.cops.common.constant.CopsParamConstant;
import cc.rengu.igas.cops.common.dao.CopsAgentInfoMapper;
import cc.rengu.igas.cops.common.dao.CopsMchntBaseInfoMapper;
import cc.rengu.igas.cops.common.dao.CopsPlatMchntInfoMapper;
import cc.rengu.igas.cops.common.dao.impl.CopsAgentInfoMapperImpl;
import cc.rengu.igas.cops.common.dao.impl.CopsMchntBaseInfoMapperImpl;
import cc.rengu.igas.cops.common.dao.impl.CopsPlatMchntInfoMapperImpl;
import cc.rengu.igas.cops.common.entity.CopsAgentInfo;
import cc.rengu.igas.cops.common.entity.CopsMchntBaseInfo;
import cc.rengu.igas.cops.common.entity.CopsPlatMchntInfo;
import cc.rengu.igas.cops.common.enums.RespCodeEnum;
import cc.rengu.igas.cops.core.service.base.ManageService;
import cc.rengu.igas.cops.facade.request.ReconFileDownloadRequest;
import cc.rengu.igas.cops.facade.response.ReconFileDownloadResponse;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.DateUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import com.alibaba.fastjson.JSON;

import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * 对账单下载
 * Created caoxuegui on 2020/6/29.
 */
public class ReconFileDownload extends ManageService {
    @Override
    protected Object bizBeforeCust() throws Exception {
        ReconFileDownloadRequest reconFileDownloadRequest = new ReconFileDownloadRequest();
        ConvertUtil.convertOutput(reconFileDownloadRequest);
        return reconFileDownloadRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        BizResponse bizResponse = new BizResponse();
        ReconFileDownloadRequest reconFileDownloadRequest = (ReconFileDownloadRequest) request;
        String instId = reconFileDownloadRequest.getHeader().getInstId();
        ReconFileDownloadResponse reconFileDownloadResponse = new ReconFileDownloadResponse();
        /* 参数合法性检查 */
        if (null == reconFileDownloadRequest.getSettleDate() || reconFileDownloadRequest.getSettleDate().isEmpty()) {
            rglog.error("请求参数清算日期<{}>不能为空!", reconFileDownloadRequest.getSettleDate());
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        if (DateUtil.compareDate(DateUtil.getCurrentDate(), reconFileDownloadRequest.getSettleDate()) <= 0) {
            rglog.error("清算日期<{}>不能大于等于当前日期<{}>!", reconFileDownloadRequest.getSettleDate(), DateUtil.getCurrentDate());
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        /* 获取对账文件存储路径：根目录/CMSC/RECON/法人行/对账日期/商户号/商户对账文件*/
        SysParamService sysParamService = new SysParamServiceImpl();
        SysParam sysParam = sysParamService.getSysParamInfo(AppParamConstant.DEFAULT_INSTID, CopsParamConstant.FILE_PATH_PARAM, CopsParamConstant.MCHNT_RECON_FILE_PATH);
        if (sysParam == null) {
            rglog.info("文件存储路径未配置");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        String filePath = sysParam.getParamValue() + File.separator + instId + File.separator + reconFileDownloadRequest.getSettleDate() + File.separator;
        String merchNo = "";
        if (!StringUtil.isEmptyOrNull(reconFileDownloadRequest.getSecMerchNo()) && !"null".equals(reconFileDownloadRequest.getSecMerchNo())) {
            rglog.debug("门店对账单下载");
            /*查询连锁商户信息*/
            CopsMchntBaseInfoMapper copsMchntBaseInfoMapper = new CopsMchntBaseInfoMapperImpl();
            CopsMchntBaseInfo copsMchntBaseInfo = copsMchntBaseInfoMapper.getMchntBaseInfoByInstIdAndMchntNo(reconFileDownloadRequest.getHeader().getInstId(), reconFileDownloadRequest.getSecMerchNo());
            if (null != copsMchntBaseInfo && "11".equals(copsMchntBaseInfo.getMchntType()) && AppParamConstant.YES.equals(copsMchntBaseInfo.getIndependentDataFlag())) {
                /*独立清算门店*/
                filePath += "MRECRSLF";
                merchNo = reconFileDownloadRequest.getSecMerchNo();
                rglog.debug("独立清算门店对账单<{}>", filePath);
            } else {
                rglog.debug("非独立清算门店或商户信息不存在");
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        } else if (!StringUtil.isEmptyOrNull(reconFileDownloadRequest.getOneMerchNo()) && !"null".equals(reconFileDownloadRequest.getOneMerchNo())) {
            rglog.debug("商户对账单下载");
            /*查询连锁商户信息*/
            CopsMchntBaseInfoMapper copsMchntBaseInfoMapper = new CopsMchntBaseInfoMapperImpl();
            CopsMchntBaseInfo copsMchntBaseInfo = copsMchntBaseInfoMapper.getMchntBaseInfoByInstIdAndMchntNo(reconFileDownloadRequest.getHeader().getInstId(), reconFileDownloadRequest.getOneMerchNo());
            if (null != copsMchntBaseInfo && "00".equals(copsMchntBaseInfo.getMchntType())) {
                filePath += "MRECRSLF";
                merchNo = reconFileDownloadRequest.getOneMerchNo();
                rglog.debug("普通商户对账单下载<{}>", filePath);
            } else if (null != copsMchntBaseInfo && "10".equals(copsMchntBaseInfo.getMchntType())) {
                filePath += "CHMRECRSLF";
                merchNo = reconFileDownloadRequest.getOneMerchNo();
                rglog.debug("连锁商户对账单下载<{}>", filePath);
            } else {
                rglog.debug("商户信息不存在");
                throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
            }
        } else if (!StringUtil.isEmptyOrNull(reconFileDownloadRequest.getOrgNo()) && !"null".equals(reconFileDownloadRequest.getOrgNo())) {
            rglog.debug("平台商户对账单下载或是代理机构对账单下载");
            /*查询平台商户*/
            CopsPlatMchntInfoMapper copsPlatMchntInfoMapper = new CopsPlatMchntInfoMapperImpl();
            CopsPlatMchntInfo copsPlatMchntInfo = copsPlatMchntInfoMapper.getOpmsPlatMchntInfoByInstIdMchntNo(reconFileDownloadRequest.getHeader().getInstId(), reconFileDownloadRequest.getOrgNo());
            if (null == copsPlatMchntInfo) {
                /*查询代理机构信息*/
                CopsAgentInfoMapper copsAgentInfoMapper = new CopsAgentInfoMapperImpl();
                CopsAgentInfo copsAgentInfo = copsAgentInfoMapper.selectAgentInfoByPrimaryKey(reconFileDownloadRequest.getHeader().getInstId(), reconFileDownloadRequest.getOrgNo());
                if (null == copsAgentInfo) {
                    rglog.debug("该商户非平台商户且非代理机构");
                    throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
                } else {
                    rglog.debug("代理机构对账单");
                    /*/epaydata/csmc/file/RECON/810/20201118/AMRECRSLF*/
                    filePath += "AMRECRSLF";
                    merchNo = reconFileDownloadRequest.getOrgNo();
                    rglog.debug("代理机构对账单<{}>", filePath);
                }
            } else {
                /*/epaydata/csmc/file/RECON/810/20201118/PMRECRSLF*/
                filePath += "PMRECRSLF";
                merchNo = reconFileDownloadRequest.getOrgNo();
                rglog.debug("平台商户对账单<{}>", filePath);
            }
        } else {

        }
        String fileName = "epay_".concat(merchNo).concat("_").concat(reconFileDownloadRequest.getSettleDate()).concat(".csv");
        String zipFileName = "epay_".concat(merchNo).concat("_").concat(reconFileDownloadRequest.getSettleDate()).concat(".zip");
        rglog.debug("================目录<{}>", filePath);
        rglog.debug("================欲下载名称<{}>", fileName);
        String zipFilePath = filePath + "/" + zipFileName;
        rglog.debug("带压缩文件<{}>", zipFilePath);

        if (fileToZip(filePath, zipFilePath, merchNo)) {
            File downloadFile = new File(zipFilePath);
            xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/ArgList",
                    "Content-Length:" +
                            "Content-Type:" +
                            "Content-disposition");
            xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/Content-Length", String.valueOf(downloadFile.length()));
            xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/Content-Type", "application/octet-stream");
            xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/Content-disposition", "attachment; filename=" + downloadFile.getName());

        } else {
            /* 组装应答信息 */
            reconFileDownloadResponse.setFileName(zipFilePath);
            bizResponse.setResult(reconFileDownloadResponse);
            bizResponse.setRspSysId(AppParamConstant.SYS_ID);
            bizResponse.setRespCode("EBPY1039");
            bizResponse.setRespDesc("对账单文件不存在");

            return bizResponse;
        }

        /* 组装应答信息 */
        reconFileDownloadResponse.setFileName(zipFilePath);
        bizResponse.setResult(reconFileDownloadResponse);
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());

        return bizResponse;

    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        ReconFileDownloadResponse reconFileDownloadResponse = (ReconFileDownloadResponse) bizResponse.getResult();
        ConvertUtil.convertInput(reconFileDownloadResponse);
    }

    /**
     * 生产压缩包
     *
     * @param filePath
     * @param zipFileName
     * @param merchNo
     */
    public boolean fileToZip(String filePath, String zipFileName, String merchNo) throws Exception {
        boolean bl = false;
        File sourceFile = new File(filePath);
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        FileInputStream fis = null;
        BufferedInputStream bis = null;
        if (!sourceFile.isDirectory()) {
            rglog.error("不是目录");
        } else {
            try {
                File[] sourceFiles = sourceFile.listFiles();
                if (null == sourceFiles || sourceFiles.length < 1) {
                    rglog.error("待压缩的文件目录<{}>里面不存在文件，无需压缩", filePath);
                } else {
                    rglog.error("ZIP包文件<{}>", zipFileName);
                    File zipFile = new File(zipFileName);
                    fos = new FileOutputStream(zipFile);
                    zos = new ZipOutputStream(new BufferedOutputStream(fos));
                    byte[] bufs = new byte[1024 * 10];
                    for (int i = 0; i < sourceFiles.length; i++) {
                        File file = sourceFiles[i];
                        if (file.getName().contains(merchNo) && !file.getName().contains(".zip")) {
                            //创建ZIP实体，并添加进压缩包
                            ZipEntry zipEntry = new ZipEntry(file.getName());
                            zos.putNextEntry(zipEntry);
                            //读取待压缩的文件并写进压缩包里
                            fis = new FileInputStream(file);
                            bis = new BufferedInputStream(fis, 1024 * 10);
                            int read = 0;
                            while ((read = bis.read(bufs, 0, 1024 * 10)) != -1) {
                                zos.write(bufs, 0, read);
                            }
                            bl = true;
                        }
                        if (null != bis) bis.close();
                        if (null != fis) fis.close();
                        if (bl) {
                            break;
                        }
                    }
                }
            } catch (IOException e) {
                rglog.debug("IO异常<{}>", JSON.toJSONString(e));
            } finally {
                try {
                    if (null != zos) zos.close();
                    if (null != fos) fos.close();
                } catch (IOException e) {
                    rglog.debug("IO异常<{}>", JSON.toJSONString(e));
                }
            }
        }
        return bl;
    }
}
